package com.berchen.线程交替;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 编写一个程序，开启三个线程，这三个线程ID分别为A、B、C，每个线程将自己的ID，在屏幕上打印10次，要求输出的结果按顺序显示。
 * 举例：ABCABCABC......
 *
 * 我们下面的程序A打印5次、B10次、C15次。一轮中，一共20轮
 *
 * 这种一个线程执行了另一个线程执行，就必须要用到线程通信才可以。
 *
 */
public class TestAlternate {

    public static void main(String[] args){

        AlternateDemo ad=new AlternateDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {

                for(int i=1;i<20;i++){

                    ad.loopA(i);
                }
            }
        },"A").start(); // 启动一个线程，并且调用方法，每一个都遍历20次。
        new Thread(new Runnable() {
            @Override
            public void run() {

                for(int i=1;i<20;i++){

                    ad.loopB(i);
                }
            }
        },"B").start();
        new Thread(new Runnable() {
            @Override
            public void run() {

                for(int i=1;i<20;i++){

                    ad.loopC(i);
                }
            }
        },"C").start();
    }
}
class AlternateDemo{

    private int number=1;   // 当前正在执行线程的标记。其值为1、2、3，值为1时A线程才能执行。

    private Lock lock=new ReentrantLock();
    private Condition c1=lock.newCondition();
    private Condition c2=lock.newCondition();
    private Condition c3=lock.newCondition();

    /**
     * @param totalLoop 循环第几轮
     */
    public void loopA(int totalLoop){

        lock.lock();

        try{
            // 1、判断
            if(number!=1){

                c1.await(); // 值不为1，A线程不能执行，所以将A线程给睡眠
            }

            // 值为1，A线程执行
            // 2、打印
            for(int i=0;i<5;i++){

                System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
            }

            // 3、唤醒B
            number=2;   // A线程执行结束，将number赋值为2，并且唤醒B线程
            c2.signal();    // 只唤醒2
        }catch (Exception e){ }
        finally {
            lock.unlock();
        }
    }
    public void loopB(int totalLoop){

        lock.lock();

        try{
            // 1、判断
            if(number!=2){

                c2.await();
            }
            // 2、打印
            for(int i=0;i<10;i++){

                System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
            }

            // 3、唤醒C
            number=3;
            c3.signal();    // 只唤醒3
        }catch (Exception e){ }
        finally {
            lock.unlock();
        }
    }
    public void loopC(int totalLoop){

        lock.lock();

        try{
            // 1、判断
            if(number!=3){

                c3.await();
            }
            // 2、打印
            for(int i=0;i<15;i++){

                System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
            }

            // 3、唤醒A
            number=1;
            c1.signal();    // 只唤醒1
        }catch (Exception e){ }
        finally {
            lock.unlock();
        }
    }
}
